#include "compat.h"
#include "popcount.h"

#include <assert.h>
#include <limits.h>

LINKAGE("C") long popcount_buffer(void const *buf, long unsigned size)
{
#ifdef __GNUC__
    typedef long unsigned popcount_t;
    if (0 != (size % sizeof(popcount_t))) {
        assert(false);
        return -1;
    }
    long bitsset = 0;
    for (long unsigned a = 0; a < size / sizeof(popcount_t); ++a)
    {
        bitsset += __builtin_popcountl(((popcount_t *)buf)[a]);
    }
#else
    typedef long unsigned popcount_t;
    if ((size % sizeof(popcount_t)) != 0) {
        assert(false);
        return -1;
    }
    long bitsset = 0;
    for (long unsigned a = 0; a < size / sizeof(popcount_t); ++a) {
        for (int b = 0; b < sizeof(popcount_t) * CHAR_BIT; ++b) {
            bitsset += ((popcount_t *)buf)[a] >> b & 1;
        }
    }
#endif
    return bitsset;
}
